#include "calculatorprocessingmessage.h"
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <math.h>
#include <QDebug>
#include <QStringList>

CalculatorProcessingMessage::CalculatorProcessingMessage(QObject *parent) :
    QObject(parent)
{
    m_infix.clear();
    m_postfix.clear();
    m_position = -1;
//    ClickEqual = false;
//    ClickOperator = false;
}

void CalculatorProcessingMessage::Acceptedclick(QString Operator)
{
    emit display(Operator);
}

int CalculatorProcessingMessage::AcceptedEqual(QString Expression)
{
    //去除表达式中所有空格
    QStringList sl = Expression.split(" ",QString::SkipEmptyParts);
    Expression = "";
    for(int i = 0; i < sl.size(); ++i)
    {
        Expression = Expression + sl.at(i);
    }

    for (int i = 0; i < Expression.size(); ++i)
    {
        if (Expression[i] == '\262')
            Expression.replace(i, 1, "^2");
    }

//    qDebug() <<"Expression : " <<Expression;

    m_infix = Expression.toLatin1();
    for (int i = 0; i < m_infix.size(); ++i)
    {
        if (m_infix[i] == '?')        //8730 == '?'
        {
//            qDebug() << "in 8730";
            m_infix[i] = '#';
        }
    }

    for (int i = 0; i < m_infix.size(); ++i)
    {
        //解决-()--()问题 将-(2+3)替换成 -1*(2+3)
        if ( (m_infix[i] == '-') && (m_infix[i + 1] == '(')
             && ( (i == 0)
                  || ((i > 0) && isOperator(m_infix[i - 1]) && (m_infix[i - 1] != ')'))  )   )
        {
            QByteArray y("-1*");
            m_infix.replace(i, 1, y);
        }
    }

//    qDebug() <<"m_infix : " <<m_infix;

    if ((inToPost()) == -1)
    {
        emit DisplayError("Input Error");
        return -1;
    }
    cancel_end();

    double Value = value();
//    qDebug() << "Value = " << Value;
//    qDebug() << Expression << " = " << Value;

    Clear();

    if (Value == '~')
    {
        emit DisplayError("Input Error");
        return -1;
    }
    else
    {
//        QString res = QString("%1").arg(Value);
        QString res = QString::number(Value, 'd', 10);
//        qDebug() << res.count();
        while ((res.right(1) == "0" && res.contains(".", Qt::CaseInsensitive))
               || res.right(1) == ".")
            res.replace(res.count() - 1, 1, "");
//            qDebug() << "NULL";
//        if (res.right(1) == ".")
//            res.replace(res.count() - 1, 1, "");
//        qDebug() << res;   //结果
//        ClickEqual = true;
        emit DisplayResult(res);
    }
}

void CalculatorProcessingMessage::AcceptedBackSpace(QString str)
{
    QString text = str;
    if ((text.size() == 1) && (text[0] == '0'))
        ;
    else
    {
        text.chop(1);
        if (text.isEmpty())
        {
            text = "0";
        }
    }

    emit displayBackSpace(text);
}

void CalculatorProcessingMessage::Clear()
{
    m_infix.clear();
    m_postfix.clear();
    m_position = -1;
}

void CalculatorProcessingMessage::push(double src)
{
    if(m_position >= MAXSIZE)
        ;       //stack is full
    else
        m_stack[++m_position] = src;               //push c into stack
}

double CalculatorProcessingMessage::pop()
{
    if(m_position < 0)
        ; //stack is empty
    else
        return m_stack[m_position--];
}

double CalculatorProcessingMessage::top()
{
    if(!isEmpty())
        return m_stack[m_position];
}

int CalculatorProcessingMessage::isEmpty()
{
    return m_position == -1 ? 1 : 0;
}

bool CalculatorProcessingMessage::isOperator(QByteRef c)
{
//    qDebug() << "in isoperator";
    if(    ('+' == c)    || ('-' == c)
        || ('*' == c)    || ('/' == c)
        || ('(' == c)    || (')' == c)
        || ('^' == c)    || ('!' == c)
        || ('#' == c)    || ('%' == c)
        || ('\367' == c) || ('\327' == c)
                             )
        return true;

    return false;
}

int CalculatorProcessingMessage::inToPost()
{
    int i, k;
    double temp = 0;
    int size = m_infix.size();
//    qDebug() << "m_infix.size = " << size;

//    if ((strncmp(infix, "help", 4)) == 0)
//    {
//        help();
//        return -2;
//    }
//    if ((strncmp(infix, "exit", 4)) == 0)
//    {
//        exit(0);
//    }

    if (isOperator(m_infix[0]))
    {
        if ( (m_infix[0] == '-')
                && isDigital(m_infix[1]) )
            ;
//            qDebug() << "hello";
        else if ((m_infix[0] != '#') && (m_infix[0] != '('))
            return -1;
    }
    for(i = 0,k = 0; i < size; i++)
    {
//        qDebug() << "for";
        if(isOperator(m_infix[i]))
        {
            //遇到运算符了
            if(')' == m_infix[i])
            {
                //遇到右括号
                if (!isOperator(m_infix[i + 1]) && (i != size - 1))
                    return -1;
                //弹出在栈中的所有元素
                while(!isEmpty())
                {
                    if('(' == (temp = pop()))
                        //遇到左括号停止输出
                        break;
                    else
                        m_postfix[k++] = temp;
                }
            }
            else if('(' == m_infix[i])
            {
                //遇到左括号
                if (!isOperator(m_infix[i - 1]) && (i != 0))
                    return -1;
                push(m_infix[i]);
            }
            else
            {
                //如果是负号，前面是运算符 除了')' ，后面是数字
                if ((m_infix[i] == '-')
                        && ((isOperator(m_infix[i - 1]) && (i > 0) && (m_infix[i - 1] != ')')) || (i == 0))
                        && (isDigital(m_infix[i + 1])))
                    //是负号
                {
//                    printf("i:%d是负号\n",i);
                    m_postfix[k++] = '-';
                }

                //处理普通运算符
                //如果栈空
                else if(isEmpty())
                {
                    //栈空就直接压入栈
                    push(m_infix[i]);
                }
                else if (!isEmpty())
                {
                    while(!isEmpty())
                    {
                        if(cmpOperator(temp=top(),m_infix[i]) >= 0)
                        {
                            //如果这里是top操作 不是pop 如果是后者要记得再执行一个push
                            pop();          //将这个字符弹出 切记
                            m_postfix[k++] = temp;
                            m_postfix[k++] = ',';
                        }
                        else
                        {
                            //push(temp);
                            //这里压回去 为什么我上面使用top会使程序出错
                            //因为那里会成为一个死循环 必须要将其弹出
                            break;
                        }
                    }
                    push(m_infix[i]);
                }
            }
        }
        else if (((m_infix[i] <= '9') && (m_infix[i] >= '0')) || (m_infix[i] == '.'))
        {
            if (m_infix[i] == '.')
            {
                if (!isDigital(m_infix[i - 1]))
                    return -1;
            }
            if ((i > 0) &&  (((m_infix[i - 1] <= '9')
                              && (m_infix[i - 1] >= '0'))
                              || (m_infix[i - 1] == '.')))
            {
                m_postfix[--k] = m_infix[i];
                m_postfix[++k] = ',';
                k++;
            }
            else
            {
                m_postfix[k++] = m_infix[i];
                m_postfix[k++] = ',';
            }
        }
        else
            return -1;
    }
    while(!isEmpty())
        m_postfix[k++] = pop();
    return k;
}

int CalculatorProcessingMessage::cmpOperator(int o1, int o2)
{
    int value1 = 0,value2 = 0;

    if ('+' == o1 || '-' == o1)
        value1 = 1;
    else if ('/' == o1 || '*' == o1 || '%' == o1 || '\327' == o1 || '367' == o1)
        value1 = 2;
    else if ('^' == o1 || '!' == o1 || '#' == o1 )
        value1 = 3;

    if ('+' == o2 || '-' == o2)
        value2 = 1;
    else if ('/' == o2 || '*' == o2 || '%' == o2 || '\327' == o2 || '367' == o2)
        value2 = 2;
    else if ('^' == o2 || '!' == o2 || '#' == o2  )
        value2 = 3;

    return value1 - value2;
}

double CalculatorProcessingMessage::value()
{
    double number1, number2;
    int i;
    //m_position = -1;
    double temp = 0, temp1 = 1;
    int index = 0;
    int size = m_postfix.size();
    double decimal = 1;
    int flag = 0;
    double Minus = 1.0;  //负数则乘以-1，初始值均为正值

    for(i = 0; i < size; i++)
    {
        if ( (m_postfix[i] == '-')
                    && ( ((m_postfix[i - 1] == ',') && (i > 0) && (isDigital(m_postfix[i + 1])))
                         || (isDigital(m_postfix[i + 1]) && (i == 0)) ) )
        {
            Minus = -1.0;
            continue;
        }
        if (((m_postfix[i] <= '9') && (m_postfix[i] >= '0')) || (m_postfix[i] == '.'))
        {
            if (m_postfix[i] != '.')
                temp = (temp * 10 + (int)(m_postfix[i] - '0'));
            if (flag)
                decimal *= 10;
            if (m_postfix[i] == '.')
                flag = 1;
        }
        if ( (m_postfix[i] == ',') && (isDigital(m_postfix[i - 1])))
        {
            if (decimal != 1)
                push(temp / decimal * Minus);
            else
                push(temp * Minus);

            temp = 0;
            flag = 0;
            decimal = 1;
            Minus = 1.0;
        }
        if (isOperator(m_postfix[i]))
        {
            number1 = 0;
            number2 = 0;

            if ((m_postfix[i] != '!') && (m_postfix[i] != '#') && (m_postfix[i] != 0x221a))
            {
                if(!isEmpty())
                    number2 = pop();
                if(!isEmpty())
                    number1 = pop();
            }
            else
            {
                if(!isEmpty())
                    number2 = pop();
            }

            switch(m_postfix[i])
            {
                case '+':
                {
                    push(number1 + number2);
                    break;
                }
                case '-':
                {
                    push(number1 - number2);
                    break;
                }
                case '\327':
                case '*':
                {
                    push(number1 * number2);
                    break;
                }
                case '\367':
                case '/':
                {
                    if(number2)
                        push(number1 / number2);
                    else
                        return '~';
                    break;
                }
                case '^':
                {
                    for (index = 0; index < number2; index++)
                    {
                        temp1 = temp1 * number1;
                    }
                    push(temp1);
                    temp1 = 1;
                    break;
                }
                case '!':
                {
                    int temp2 = (int)number2 / 1;

                    if (temp2 < 0)
                        return '~';
                    if (temp2 == 0 || temp2 == 1)
                    {
                        push(1);
                        break;
                    }
                    for (index = temp2 - 1; index > 0; index--)
                    {
                        temp2 = temp2 * index;
                    }
                    //printf("temp2:%d\n",temp2);
                    push(temp2);
                    break;
                }
                case '#':
                {
                    if (number2 >= 0)
                        push(sqrt(number2));
                    else
                    {
                        return '~';
                    }
                    break;
                }
                case '%':
                {
                    if (number2 >= 0)
                    {
                        push((int)number1 % (int)number2);
                    }
                    else
                        return '~';
                    break;
                }
                default :
                    return '~';
            }
        }
    }

    if(m_position == 0)
    {
        return m_stack[0];
    }
    else
        return '~';
}

//int CalculatorProcessingMessage::my_strlen(QByteArray src)
//{
//    int total = 0;
//    while (*(src + total) != '\n')
//        total++;
//    return total;
//}

//void CalculatorProcessingMessage::cancel_spaces(QByteArray src)
//{
//    int len = my_strlen(src);
//    *(src + len) = '\0';
//    char buf[MAXSIZE + 1];
//    int i = 0, j = 0;
//    int space_number = 0;
//    for (i; i < len; i++)
//    {
//        if (*(src + i) == ' ')
//        {
//            space_number++;
//        }
//        else
//        {
//            buf[j++] = *(src + i);
//        }
//    }
//    *(buf + j) = '\0';
//    memset(src, 0, sizeof(src));
//    strncpy(src, buf, len - space_number + 1);
//}

bool CalculatorProcessingMessage::isDigital(QByteRef c)
{
    if (c <= '9' && c >= '0')
        return true;

    return false;
}

void CalculatorProcessingMessage::cancel_end()
{
    int len = m_postfix.size();
    while (!isOperator(m_postfix[len]))
        len--;
    m_postfix[len + 1] = '\0';
}
